#pragma once
#include <string>
#include <map>
#include <set>
#include <vector>
#include <pthread.h>

class BBS2chProxyKeyManager {
public:
	struct Cookie {
		std::string name;
		std::string value;
		std::string domain;
		bool includeSubdomains;
		std::string path;
		bool secure;
		std::string expires;
		Cookie() : includeSubdomains(true), path("/"), secure(), expires("0") {};
		Cookie(const std::string &value);
		std::string valueInNetscapeFormat();
		bool isExpired();
		bool isSameAs(Cookie &cookie);
		void *jsonValue();
	};
	class CookieJar {
	private:
		std::vector<Cookie> _cookies;
		pthread_mutex_t _mutex;
	public:
		time_t timeAcornSynced;
		time_t timeBeSynced;
		time_t timeUpliftSynced;
		CookieJar() : timeAcornSynced(), timeBeSynced(), timeUpliftSynced() {
			pthread_mutex_init(&_mutex, NULL);
		};
		~CookieJar() {
			pthread_mutex_destroy(&_mutex);
		};
		std::vector<Cookie>& getList();
		void set(Cookie &cookie);
		void clear();
		void lock();
		void unlock();
		void *jsonValue();
	};
private:
	std::map<std::string, std::string> _keys;
	std::map<std::string, double> _keyIssueTimes;
	std::set<std::string> _expiredKeys;
	pthread_mutex_t _mutex;
	std::string _lastKey;
	std::string _storagePath;
	std::map<std::string, CookieJar> _cookies;
	static const std::string _emptyKey;
public:
	BBS2chProxyKeyManager() {
		pthread_mutex_init(&_mutex, NULL);
	};
	~BBS2chProxyKeyManager() {
		pthread_mutex_destroy(&_mutex);
	};
	const std::string& getKey();
	const std::string& getKey(const std::string &userAgent);
	void setKey(const std::string &key, const std::string &oldKey, const std::string &userAgent, int reason);
	bool isExpired(const std::string &key);
	double secondsToWaitBeforePosting(const std::string &key);
	void setStorage(const char *jsonPath);
	int loadKeys();
	CookieJar& getCookieJar(const std::string &userAgent, bool syncCookie=false);
	bool flushCookies();
	std::string cookieManagerHTML();
private:
	bool saveKeys();
};
